﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;

namespace LaoLuo.Net.Mail
{
    /// <summary>
    /// using <see cref="System.Net.Mail.SmtpClient"/> inside, the benefit is multi <see cref="NetworkCredential"/> can be used, when <see cref="Send"/> is called, a random <see cref="NetworkCredential"/> will be used to do the work
    /// </summary>
    public class SmtpClient : IDisposable
    {
        private readonly string _host;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="host"></param>
        /// <param name="networkCredentials"> </param>
        public SmtpClient(string host, params NetworkCredential[] networkCredentials)
            : this(host, networkCredentials.AsEnumerable())
        {
            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="host"></param>
        /// <param name="networkCredentials"></param>
        public SmtpClient(string host, IEnumerable<NetworkCredential> networkCredentials)
        {
            _host = host;
            NetworkCredentials = networkCredentials == null ? new HashSet<NetworkCredential>() : new HashSet<NetworkCredential>(networkCredentials);
        }

        private HashSet<NetworkCredential> NetworkCredentials { get; set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="networkCredentials"> </param>
        public void AddNetworkCredentials(IEnumerable<NetworkCredential> networkCredentials)
        {
            foreach (var networkCredential in networkCredentials)
            {
                NetworkCredentials.Add(networkCredential);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mailMessage"></param>
        /// <returns>the <see cref="NetworkCredential"/> that was used to send</returns>
        public NetworkCredential Send(MailMessage mailMessage)
        {
            return SendWithNetworkCredential(mailMessage, GetRandomNetworkCredential());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="to"></param>
        /// <param name="subject"></param>
        /// <param name="body"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public NetworkCredential SendHtml(string to, string subject, string body, Encoding encoding)
        {
            var networkCredential = GetRandomNetworkCredential();

            using (var mailMessage = new MailMessage(networkCredential.UserName, to)
                                         {
                                             BodyEncoding = encoding,
                                             Subject = subject,
                                             Body = body,
                                             IsBodyHtml = true
                                         })
            {
                return SendWithNetworkCredential(mailMessage, networkCredential);
            }
        }

        private NetworkCredential SendWithNetworkCredential(MailMessage mailMessage, NetworkCredential networkCredential)
        {
            using (var client = new System.Net.Mail.SmtpClient(_host))
            {
                client.Credentials = networkCredential;

                client.Send(mailMessage);

                return networkCredential;
            }
        }

        private NetworkCredential GetRandomNetworkCredential()
        {
            if (NetworkCredentials == null || NetworkCredentials.Count == 0)
            {
                throw new ApplicationException("no NetworkCredential found");
            }

            return NetworkCredentials.RandomSingle();
        }


        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            NetworkCredentials.Clear();
            NetworkCredentials = null;
        }
    }
}
